﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Windows;
using System.Windows.Threading;
using System.Windows.Input;
using System.ComponentModel;

namespace Xceed.Silverlight.DataGrid
{
  #region Metadata

  [TemplateVisualState( GroupName = "VisibilityStates", Name = "Visible" )]
  [TemplateVisualState( GroupName = "VisibilityStates", Name = "Hidden" )]

  #endregion // Metadata

  public class NotificationControl : ControlBase, INotifyPropertyChanged
  {
    private static readonly string VisibilityStateVisible = "Visible";
    private static readonly string VisibilityStateHidden = "Hidden";

     public NotificationControl()
      : base()
    {
      this.DefaultStyleKey = typeof( NotificationControl );
      this.VisualStateHelper = new VisualStateHelper( this );

      this.InitializeTimer();
    }

     #region AutoHideDelay Property

     public static readonly DependencyProperty AutoHideDelayProperty = DependencyProperty.Register(
       "AutoHideDelay",
       typeof( int ),
       typeof( NotificationControl ),
       new PropertyMetadata( 5000, new PropertyChangedCallback( NotificationControl.OnAutoHideDelayPropertyChanged ) ) );

     public int AutoHideDelay
     {
       get
       {
         return ( int )this.GetValue( NotificationControl.AutoHideDelayProperty );
       }
       set
       {
         this.SetValue( NotificationControl.AutoHideDelayProperty, value );
       }
     }

     private static void OnAutoHideDelayPropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
     {
       NotificationControl notificationControl = ( NotificationControl )sender;
       if( notificationControl.m_timer != null )
       {
         notificationControl.m_timer.Interval = TimeSpan.FromMilliseconds( notificationControl.AutoHideDelay );
       }
     }

     #endregion // AutoHideDelay Property

     #region Close Command

     internal static readonly DependencyProperty CloseCommandProperty = DependencyProperty.Register(
       "CloseCommand",
       typeof( ICommand ),
       typeof( NotificationControl ),
       new PropertyMetadata( null ) );

     public ICommand CloseCommand
     {
       get
       {
         return ( ICommand )this.GetValue( NotificationControl.CloseCommandProperty );
       }
       private set
       {
         this.SetValue( NotificationControl.CloseCommandProperty, value );
       }
     }

     private void OnCloseCommandExecuted( object parameter )
     {
       this.IsVisible = false;
     }

     #endregion // Close Command

     #region IsVisible Property (Private)

     private bool IsVisible
     {
       get
       {
         return m_isVisible;
       }
       set
       {
         if( m_isVisible == value )
           return;

         m_isVisible = value;
         this.UpdateVisibilityStates( true );
       }
     }

     private bool m_isVisible;

     #endregion IsVisible Property

     #region Notification Property

     public string Notification
     {
       get
       {
         return m_notification;
       }
       private set
       {
         if( m_notification == value )
           return;

         m_notification = value;
         this.RaisePropertyChanged( "Notification" ); 
       }
     }

     private string m_notification; // = null

     #endregion // Notification Property

     #region Show Command

     internal static readonly DependencyProperty ShowCommandProperty = DependencyProperty.Register(
      "ShowCommand",
      typeof( ICommand ),
      typeof( NotificationControl ),
      new PropertyMetadata( null ) );

     public ICommand ShowCommand
     {
       get
       {
         return ( ICommand )this.GetValue( NotificationControl.ShowCommandProperty );
       }
       private set
       {
         this.SetValue( NotificationControl.ShowCommandProperty, value );
       }
     }

     private void OnShowCommandExecuted( object parameter )
     {
       this.IsVisible = true;
     }

     #endregion // Show Command

     #region VisualState Property (Internal)

     internal VisualStateHelper VisualStateHelper
     {
       get;
       private set;
     }

     #endregion VisualState Property

     public override void OnApplyTemplate()
     {
       base.OnApplyTemplate();
       this.VisualStateHelper.ApplyVisualStates();
     }

     protected override void OnMouseEnter( MouseEventArgs e )
     {
       base.OnMouseEnter( e );

       if( this.IsVisible )
       {
         // This is to prevent the NotificationControl from 
         // hiding itself when the mouse is over it.
         m_timer.Stop();
       }
     }

     protected override void OnMouseLeave( MouseEventArgs e )
     {
       base.OnMouseLeave( e );

       if( this.IsVisible )
       {
         // Restart the timer to close the NotificationControl after the delay.
         m_timer.Start();
       }
     }

     internal void UpdateVisibilityStates( bool useTransitions )
     {
       if( this.IsVisible )
       {
         this.VisualStateHelper.GoToVisibilityState( NotificationControl.VisibilityStateVisible, useTransitions );
       }
       else
       {
         this.VisualStateHelper.GoToVisibilityState( NotificationControl.VisibilityStateHidden, useTransitions );
       }
     }

     internal void CreateCommands()
     {
       this.ShowCommand = new DataGridCommand( new Action<object>( this.OnShowCommandExecuted ) );
       this.CloseCommand = new DataGridCommand( new Action<object>( this.OnCloseCommandExecuted ) );
     }

     internal void ReleaseCommands()
     {
       // These commands need to be released to prevent Silverlight leak
       this.ShowCommand = null;
       this.CloseCommand = null;
     }

     internal void OnNotificationReceived( object sender, NotificationReceivedEventArgs e )
     {
       this.Notification = e.NotificationMessage;
       this.IsVisible = true;

       m_timer.Stop();
       m_timer.Start();
     }

     private void InitializeTimer()
     {
       m_timer = new DispatcherTimer();
       m_timer.Tick += new EventHandler( this.OnTimerTick );
       m_timer.Interval = TimeSpan.FromMilliseconds( this.AutoHideDelay );
     }

     private void OnTimerTick( object sender, EventArgs e )
     {
       m_timer.Stop();

       this.Notification = null;
       this.IsVisible = false;
     }

     #region INotifyPropertyChanged Members

     public event PropertyChangedEventHandler PropertyChanged;

     protected void RaisePropertyChanged( string name )
     {
       Xceed.Silverlight.DataGrid.Utils.ReflectionHelper.ValidatePublicPropertyName( this, name );

       if( this.PropertyChanged != null )
       {
         this.PropertyChanged( this, new PropertyChangedEventArgs( name ) );
       }
     }

     #endregion

     private DispatcherTimer m_timer; // = null
  }
}
